feat: Integrate BME680 Bosch BSEC support for RAK4631#2634
Conversation
This is a consolidation of my changes for BME680 on RAK4631 nodes. I will close my other PRs related to this and link back to this one. *Background on change:* This change replaces the Adafruit BME680 driver on RAK4631 with the Bosch BSEC library. Other boards continue to use the existing Adafruit path via ENV_INCLUDE_BME680. This makes the IAQ portion of the sensor functional, and more accurate. It also contains the math and/or CayenneLPP fixes from my other PRs. The Bosch code also appears to handle calibrating sensor aging as well, whereas the Adafruit code is just looking at blind values that can drift with time. Pretty cool to see this shooting out useful data! RAK4631 platform.io is set to override to ENV_INCLUDE_BME680_BSEC while leaving the Adafruit code for other node types. (If this becomes applicable for other node types in future, awesome! I just don't have hardware to test against.) Using the BSEC library introduces IAQ sensor calibration, and saves the calibration state periodically so it does not have to calibrate again later. At startup the IAQ sensor takes 30 minutes to heat and to hit a baseline, then starts calibrating. Once calibrated, it will save those settings and will only write settings again if calibration falls back and restores back to state 3. This fix also has the gas resistance math fix that was in [pull 2146](meshcore-dev#2146) so the adafruit path also can at least show accurate values instead of looping negative. Also includes the fix from [pull 2149](meshcore-dev#2149) so the pressure output isn't truncated to 1hPa steps. *Fixes/Changes:* - Add bsec_config_iaq[] with the 3.3V/3s-LP/28d calibration profile - BSEC init applies setConfig() for voltage-correct heater targeting - IAQ, heat-compensated temperature/humidity, pressure, and altitude reported over CayenneLPP - IAQ accuracy reported as analog input over CayenneLPP (0,1,2,3) - Calibration state persisted to /bsec_state.bin on nRF52 internal flash; written only when iaqAccuracy improves to >= 2, should keep write frequency well within flash endurance over device lifetime - Fix non-BSEC query_bme680: float pressure division, addGenericSensor for gas resistance (was addAnalogInput, overflows at > 327 Ohm) - loop() correctly gated for both GPS and BSEC-only builds - Add fix_bsec_lib.py extra_script to resolve nRF52840 hard-float ABI mismatch in Bosch's PlatformIO packaging, silly Bosch One general note outside of this code change: I noticed while BME680 _functions_ in companion nodes, since companion nodes run Bluetooth, BLE preempts the CPU, and can do so mid-I2C-transaction. This can cause the BME680 to see an anomaly and drop calibration and start a recalibrate. This is behavior that will exist (and has existed) regardless of using the Adafruit or Bosch paths. This particular companion behavior does not seem to occur in sensor or repeater nodes since their BLE is off. Probably affects other I2C devices as well. *Tests:* - RAK19003 - RAK19007 - RAK19001 - repeater, sensor, companion
|
My other two PRs are closed and this is the source of truth for my BME680 stuff now, trying to not make too many GitHub messes 😂 🎉 |
I put it back and test-compiled a few builds.
| bsec_accuracy = bsec_iaq.iaqAccuracy; | ||
| bsec_data_ready = true; | ||
| if (bsec_accuracy >= 2 && bsec_accuracy > prev_accuracy) | ||
| bsec_save_state(); |
There was a problem hiding this comment.
There doesn't appear to be any backoff here. If accuracy is updating every loop(), you will be doing a lot of filesystem writes. And there are concerns in other threads about RAKs corrupting their filesystem during writes under various trigger conditions. Maybe update this to include a millis() check as well, so that it isn't constantly overwriting the state file in rapid succession? How important is it that it update the state persistence? Could it limit it to every minute? five minutes? Or does the BSEC library itself already gate accuracy checks and so you have an inherent backoff from the library?
There was a problem hiding this comment.
Oooh, that's a good observation, I like it. Once the sensor gets into a calibrated state (except for on companions) it just remains there for hours on end. If the sensor gets into a calibration flux like on companions, it would otherwise be writing very frequently as you said. I will check into that.
I'm on a wild tear today! Trying to take advantage of it.
This is a consolidation of my changes for BME680 on RAK4631 nodes. I will close my other PRs related to this and link back to this one.
Background on change:
This change replaces the Adafruit BME680 driver on RAK4631 with the Bosch BSEC library. Other boards continue to use the existing Adafruit path via ENV_INCLUDE_BME680.
This makes the IAQ portion of the sensor functional, and more accurate. It also contains the math and/or CayenneLPP fixes from my other PRs. The Bosch code also appears to handle calibrating sensor aging as well, whereas the Adafruit code is just looking at blind values that can drift with time. Pretty cool to see this shooting out useful data!
RAK4631 platform.io is set to override to ENV_INCLUDE_BME680_BSEC while leaving the Adafruit code for other node types. (If this becomes applicable for other node types in future, awesome! I just don't have hardware to test against.)
Using the BSEC library introduces IAQ sensor calibration, and saves the calibration state periodically so it does not have to calibrate again later.
At startup the IAQ sensor takes 30 minutes to heat and to hit a baseline, then starts calibrating. Once calibrated, it will save those settings and will only write settings again if calibration falls back and restores back to state 3.
This fix also has the gas resistance math fix that was in pull 2146 so the adafruit path also can at least show accurate values instead of looping negative.
Also includes the fix from pull 2149 so the pressure output isn't truncated to 1hPa steps.
Fixes/Changes:
One general note outside of this code change: I noticed while BME680 functions in companion nodes, since companion nodes run Bluetooth, BLE preempts the CPU, and can do so mid-I2C-transaction.
This can cause the BME680 to see an anomaly and drop calibration and start a recalibrate. This is behavior that will exist (and has existed) regardless of using the Adafruit or Bosch paths.
This particular companion behavior does not seem to occur in sensor or repeater nodes since their BLE is off. Probably affects other I2C devices as well.
Tests:
24 Hour Grafana Stats Example: (Graph gap is from a service restart, not the node.)
